package controller.commoncontroller;

import java.awt.BorderLayout;

import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.EventObject;

import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.filechooser.FileFilter;
import view.UtilityConstants;
import view.commonview.LocsiFrame;
import view.commonview.TabbedPane;
import view.simulationview.SimulationArea;
import model.editormodel.EditorModel;

/**
 * Utility-Klasse <br>
 * <b>Funktion:</b> Dient zur zentralen Sammlung aller benoetigten Methoden zum
 * Oeffnen von verschiedenen Dialogfenstern.
 * 
 * @author Team Locsi
 * 
 */
public class UtilityDialogs {

	private static JPanel dialogPanel = new JPanel();
	private static JPanel northPanel = new JPanel();
	private static JDialog waitDialog;
	private static JButton button = new JButton("Schließen");
	private static JFrame myFrame;
	private static int checkCount = 3;
	private static int checkOk = 0;
	public static final String XML_EXTENSION = ".xml";
	public static final String PNG_EXTENSION = ".png";
	public static final String JPG_EXTENSION = ".jpg";
	public static final String GIF_EXTENSION = ".gif";
	public static final String BMP_EXTENSION = ".bmp";
	public static final String TXT_EXTENSION = ".txt";
	public static final String CSV_EXTENSION = ".csv";
	private static final String allowedChars = "[^a-zA-Z0-9 _.]";
	private final static String newline = System.getProperty("line.separator");
	private final static ClassLoader loader = new ClassLoader() {
	};

	/**
	 * Privater Konstruktor, da diese Klasse eine Utility-Klasse darstellt und
	 * somit kein Objekt dieser Klasse erzeugt werden soll/kann.
	 */
	private UtilityDialogs() {
	}

	/**
	 * Diese Methode macht prinzipiell das selbe wie saveDialog. Oeffnet einen
	 * FileChooser und laesst den Benutzer das Ziel auswaehlen an dem
	 * gespeichert werden soll. Der Unterschied ist, dass diese Methode den
	 * String zurueckgibt an dem gespeichert werden soll. saveDialog hingegen
	 * gibt nichts zurueck und fuehrt die speichern-Operation selbst durch.
	 * 
	 * @param caller
	 *            Das Objekt, dass diese Methode aufgerufen hat
	 * @param extension
	 *            die Dateiendung unter der die Datei dann gespeichert werden
	 *            soll (wird an den String hinten angehaengt)
	 * @param preName
	 *            name der als Vorauswahl im JFileChooser angezeigt werden soll
	 *            (wird nur benoetigt beim Abspeichern einer
	 *            csv-truthtable-datei)
	 * @return der absolute Pfad unter dem gespeichert werden soll
	 */
	public static String save2Dialog(Object caller, String extension,
			String preName) {
		JFileChooser fileChooser = new JFileChooser();

		// Setzt das Defaultverzeichnis, je nachdem von welcher Instanz caller
		// ist
		if (caller instanceof TabbedPane) {
			File picDir = new File(UtilityConstants.PICTURES_DIRECTORY);
			if (!picDir.exists()) {
				picDir.mkdir();
			}
			fileChooser.setCurrentDirectory(picDir);
		} else if (caller instanceof EditorModel) {
			File circuitDir = new File(UtilityConstants.SAVED_CIRCUITS);
			if (!circuitDir.exists()) {
				circuitDir.mkdir();
			}
			fileChooser.setCurrentDirectory(new File(
					UtilityConstants.SAVED_CIRCUITS));
			fileChooser
					.setSelectedFile(new File(((EditorModel) caller)
							.getCircuitModel().getName()
							+ UtilityDialogs.XML_EXTENSION));
		} else if (caller instanceof JTextArea) {
			File protDir = new File(UtilityConstants.PROTOCOLL_DIRECTORY);
			if (!protDir.exists()) {
				protDir.mkdir();
			}
			fileChooser.setCurrentDirectory(new File(
					UtilityConstants.PROTOCOLL_DIRECTORY));
		} else if (caller instanceof SimulationArea) {
			File ttDir = new File(UtilityConstants.TRUTHTABLE_DIRECTORY);
			if (!ttDir.exists()) {
				ttDir.mkdir();
			}
			fileChooser.setCurrentDirectory(new File(
					UtilityConstants.TRUTHTABLE_DIRECTORY));
			fileChooser.setSelectedFile(new File(preName));
		}

		calibrationOfFileChooser(fileChooser, extension);
		int userSelection = fileChooser.showSaveDialog(null);

		// User klickt im JFileChooser auf "Speichern"
		if (userSelection == JFileChooser.APPROVE_OPTION) {

			// Dateiname, den der User vergeben hat
			String fileName = fileChooser.getSelectedFile().getName();

			// Falls der User die Dateiendung nicht angibt, wird diese
			// automatisch vervollstaendigt
			if (!fileName.toLowerCase().endsWith(extension)) {
				fileName = fileName + extension;
			}

			// Wird benoetigt zur Ueberpruefung, ob die Datei schon existiert.
			// Falls der User die Dateiendung nicht mit eingegeben hatte, wurde
			// diese zuvor vervollstaendigt. Dazu wird deshalb hier ein neues
			// "File"-Objekt erzeugt, das den aktualisierten Namen enthaelt.
			File newFile = new File(fileChooser.getSelectedFile().getParent(),
					fileName);

			// Pfad, unter dem gespeichert werden soll
			String path = newFile.toString();

			// Falls der Dateiname schon existiert, wird der User gefragt, ob er
			// die Datei ersetzen will
			if (newFile.exists()) {
				int askForOverwrite = JOptionPane.showConfirmDialog(myFrame,
						newFile.getName()
								+ " ist bereits vorhanden! Möchten Sie"
								+ " die Datei ersetzen?", "Achtung!",
						JOptionPane.YES_NO_CANCEL_OPTION);

				// Wenn der User eine vorhandene Datei ersetzen will, wird
				// dies gemacht.
				if (askForOverwrite == JOptionPane.YES_OPTION) {
					return path;
				} else {
					return save2Dialog(caller, extension, preName);
				}

				// datei existiert eh noch nicht
			} else {
				return path;
			}
		} else {
			return null;
		}
	}

	/**
	 * Oeffnet einen <code>JFileChooser</code>, mit dessen Hilfe die aktuelle
	 * Schaltung in einem bestimmten Format gespeichert werden kann.
	 * 
	 * @param caller
	 *            <code>Object</code> - Ist entweder Referenz auf das
	 *            <code>TabbedPane</code>, auf das <code>EditorModel</code> oder
	 *            ein <code>JTextArea</code>-Objekt
	 * 
	 * @param extension
	 *            <code>String</code> - Das Format, in dem gespeichert werden
	 *            soll
	 */
	public static void saveDialog(Object caller, String extension) {
		JFileChooser fileChooser = new JFileChooser();

		// Setzt das Defaultverzeichnis, je nachdem von welcher Instanz caller
		// ist
		if (caller instanceof TabbedPane) {
			File picDir = new File(UtilityConstants.PICTURES_DIRECTORY);
			if (!picDir.exists()) {
				picDir.mkdir();
			}
			fileChooser.setCurrentDirectory(picDir);
		} else if (caller instanceof EditorModel) {
			File circuitDir = new File(UtilityConstants.SAVED_CIRCUITS);
			if (!circuitDir.exists()) {
				circuitDir.mkdir();
			}
			fileChooser.setCurrentDirectory(new File(
					UtilityConstants.SAVED_CIRCUITS));
			fileChooser.setSelectedFile(new File(((EditorModel) caller)
					.getCircuitModel().getName()));
		} else if (caller instanceof JTextArea) {
			File protDir = new File(UtilityConstants.PROTOCOLL_DIRECTORY);
			if (!protDir.exists()) {
				protDir.mkdir();
			}
			fileChooser.setCurrentDirectory(new File(
					UtilityConstants.PROTOCOLL_DIRECTORY));
		}

		calibrationOfFileChooser(fileChooser, extension);
		int userSelection = fileChooser.showSaveDialog(null);

		// User klickt im JFileChooser auf "Speichern"
		if (userSelection == JFileChooser.APPROVE_OPTION) {

			// Dateiname, den der User vergeben hat
			String fileName = fileChooser.getSelectedFile().getName();

			// Falls der User die Dateiendung nicht angibt, wird diese
			// automatisch vervollstaendigt
			if (!fileName.toLowerCase().endsWith(extension)) {
				fileName = fileName + extension;
			}

			// Wird benoetigt zur Ueberpruefung, ob die Datei schon existiert.
			// Falls der User die Dateiendung nicht mit eingegeben hatte, wurde
			// diese zuvor vervollstaendigt. Dazu wird deshalb hier ein neues
			// "File"-Objekt erzeugt, das den aktualisierten Namen enthaelt.
			File newFile = new File(fileChooser.getSelectedFile().getParent(),
					fileName);

			// Pfad, unter dem gespeichert werden soll
			String path = newFile.toString();

			// Falls der Dateiname schon existiert, wird der User gefragt, ob er
			// die Datei ersetzen will
			if (newFile.exists()) {
				int askForOverwrite = JOptionPane.showConfirmDialog(myFrame,
						newFile.getName()
								+ " ist bereits vorhanden! Möchten Sie"
								+ " die Datei ersetzen?", "Achtung!",
						JOptionPane.YES_NO_CANCEL_OPTION);

				// Wenn der User eine vorhandene Datei ersetzen will, wird dies
				// gemacht.
				if (askForOverwrite == JOptionPane.YES_OPTION) {

					if (caller instanceof TabbedPane) {
						((TabbedPane) caller).exportAsPicture(path);
					} else if (caller instanceof EditorModel) {
						((EditorModel) caller).saveCircuit(fileName, path);
					} else if (caller instanceof JTextArea) {
						try {
							FileWriter fw = new FileWriter(path);
							fw.write(((JTextArea) caller).getText());
							fw.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

				} else if (askForOverwrite == JOptionPane.NO_OPTION) {

					// Will der User eine vorhandene Datei nicht ersetzen,
					// erhaelt er die erneute Moeglichkeit, die Datei unter
					// anderem Namen zu speichern.
					saveDialog(caller, extension);
				}
			} else {
				// Existiert der Dateiname noch nicht, wird unter dem, vom User
				// gewaehlten Namen, gespeichert
				if (caller instanceof TabbedPane) {
					((TabbedPane) caller).exportAsPicture(path);
				} else if (caller instanceof EditorModel) {
					((EditorModel) caller).saveCircuit(fileName, path);
				} else if (caller instanceof JTextArea) {
					try {
						FileWriter fw = new FileWriter(path);
						fw.write(((JTextArea) caller).getText());
						fw.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * Schliesst den Dialog, der in <code>showCheckDialog()</code> gestartet
	 * wurde.
	 */
	public static void disposeCheckDialog() {
		JPanel buttonPanel = new JPanel();
		buttonPanel.setLayout(new FlowLayout());
		buttonPanel.add(button);
		waitDialog.add(buttonPanel, BorderLayout.SOUTH);
		button.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				myFrame.setEnabled(true);
				waitDialog.dispose();
			}
		});

		waitDialog.validate();
	}

	/**
	 * Oeffnet den Dialog zur Abfrage, ob die aktuelle Schaltung gespeichert
	 * werden soll.
	 * 
	 * @param caller
	 *            <code>Object</code> - Ist entweder Referenz auf das
	 *            <code>TabbedPane</code>, oder auf das <code>EditorModel</code>
	 * 
	 * @param extension
	 *            <code>String</code> - Das Format, in dem gespeichert werden
	 *            soll
	 * 
	 * @return <code>int</code> - <i>0</i> fuer <i>JA</i>, <i>1</i> fuer
	 *         <i>NEIN</i>, <i>2</i> fuer <i>ABBRECHEN</i> und <i>-1</i> fuer
	 *         den <i>Exit-Button in der Titelleiste</i>
	 */
	protected static int askForSave(Object caller, String extension) {
		int toReturn = JOptionPane.showConfirmDialog(myFrame,
				"Soll die aktuelle Schaltung gespeichert werden?", "LOCSI",
				JOptionPane.YES_NO_CANCEL_OPTION);

		// Wenn User die Frage bejaht
		if (toReturn == JOptionPane.YES_OPTION) {
			saveDialog(caller, extension);
		}
		return toReturn;
	}

	/**
	 * Oeffnet einen <code>JFileChooser</code>, mit dessen Hilfe eine Datei
	 * geladen werden kann.
	 * 
	 * @param eModel
	 *            <code>EditorModel</code> - Referenz auf das
	 *            <code>EditorModel</code>
	 * 
	 * @param extension
	 *            <code>String</code> - Format der zu ladenden Datei
	 * 
	 * @param caller
	 *            <code>Object</code> - Ist entweder Referenz auf den
	 *            <code>ComponentImportListener</code> oder den
	 *            <code>LoadCircuitListener</code>
	 */
	protected static void loadDialog(EditorModel eModel, String extension,
			Object caller) {

		// Speichern-Abfrage nur, wenn schaltung nicht leer ist
		if (!eModel.isEmptyCircuit()) {

			// Gibt an, was User beim JDialog ausgewaehlt hat
			int askForSaveDialog = UtilityDialogs.askForSave(eModel,
					UtilityDialogs.XML_EXTENSION);

			// User bejaht oder verneint die Frage, ob die aktuelle Schaltung
			// gespeichert werden soll, bricht also nicht ab
			if ((askForSaveDialog == JOptionPane.OK_OPTION)
					|| (askForSaveDialog == JOptionPane.NO_OPTION)) {
				createLoadDialog(eModel, extension, caller);
			}
		} else {
			createLoadDialog(eModel, extension, caller);
		}

	}

	/**
	 * Diese Methode oeffnet ein <code>JOptionPane</code> mit dessen Hilfe der
	 * User ein selbstdefiniertes Bauteil, unter einem selbst gewaehlten Namen,
	 * abspeichern kann.
	 * 
	 * @param eModel
	 *            <code>EditorModel</code> - Referenz auf das
	 *            <code>EditorModel</code>
	 */
	protected static void exportAsComponentDialog(EditorModel eModel) {
		String selfdefinedModelName = (String) JOptionPane.showInputDialog(
				myFrame, "Bitte geben Sie einen Namen fuer das Bauteil ein",
				"Als Bauteil exportieren", JOptionPane.INFORMATION_MESSAGE);
		String nameToCheck = selfdefinedModelName;

		// Wenn der User nicht auf "Abbrechen" drueckt
		if (selfdefinedModelName != null) {

			// Der Name, den der User eingegeben hat, wird hier kopiert,
			// allerdings werden alle "verbotenen" Zeichen entfernt
			String nameWithoutUnallowedChars = nameToCheck.replaceAll(
					allowedChars, "");

			// Falls der User keinen Namen eingegeben hat
			if (selfdefinedModelName.trim().length() == 0) {
				JOptionPane.showMessageDialog(myFrame,
						"Bitte geben Sie einen gültigen Namen ein!",
						"Achtung!", JOptionPane.ERROR_MESSAGE);
				exportAsComponentDialog(eModel);
			} else if (!nameToCheck.equals(nameWithoutUnallowedChars)) {

				// Besteht der Name, den der User gewaehlt hat, nicht aus den
				// erlaubten Zeichen, erhaelt er eine Fehlermeldung
				JOptionPane.showMessageDialog(myFrame,
						"Es sind nur die Zeichen a-z, A-Z, 0-9, _, "
								+ "Leerzeichen und . erlaubt!", "Achtung!",
						JOptionPane.ERROR_MESSAGE);
				exportAsComponentDialog(eModel);
			} else {

				// Falls der User die Dateiendung nicht angibt, wird diese
				// automatisch vervollstaendigt
				if (!nameToCheck.toLowerCase().endsWith(
						UtilityDialogs.XML_EXTENSION)) {
					nameToCheck = nameToCheck + UtilityDialogs.XML_EXTENSION;
				}
				File newFile = new File(UtilityConstants.SD_DIRECTORY,
						nameToCheck);

				// Falls der Dateiname noch nicht existiert, wird dem User
				// mitgeteilt, ob die aktuelle Schaltung als Bauteil gespeichert
				// werden konnte
				if (!newFile.exists()) {
					EditorModel.SaveCircuitResponse response = eModel
							.exportComponent(selfdefinedModelName);
					if (response == EditorModel.SaveCircuitResponse.SAVE_OK) {
						JOptionPane.showMessageDialog(myFrame,
								"Die aktuelle Schaltung wurde als Bauteil"
										+ " gespeichert!", "LOCSI",
								JOptionPane.INFORMATION_MESSAGE);
						((LocsiFrame) myFrame).getTabs().exportAsPicture(
								UtilityConstants.SD_DIRECTORY
										+ selfdefinedModelName + PNG_EXTENSION);
					} else if (response == EditorModel.SaveCircuitResponse.NAME_ALREADY_DEFINED) {
						JOptionPane.showMessageDialog(myFrame,
								"Die aktuelle Schaltung konnte nicht als"
										+ " Bauteil gespeichert werden,"
										+ newline
										+ "da der Name bereits in der "
										+ "Schaltung verwendet wird!",
								"Achtung!", JOptionPane.ERROR_MESSAGE);
					} else if (response == EditorModel.SaveCircuitResponse.SOME_CHECK_FAILED) {
						JOptionPane.showMessageDialog(myFrame,
								"Die aktuelle Schaltung konnte nicht als"
										+ " Bauteil gespeichert werden,"
										+ newline + "da es die Eigenschaften"
										+ " eines Bauteils nicht erfüllt"
										+ newline
										+ "(führe Checks für weitere "
										+ "Informationen aus)!", "Achtung!",
								JOptionPane.ERROR_MESSAGE);
					}
				} else {

					// Falls der Name bereits vergeben ist, wird dies dem User
					// mitgeteilt und er erhaelt die erneute Moeglichkeit, die
					// aktuelle Schaltung als Bauteil zu speichern
					JOptionPane.showMessageDialog(myFrame,
							"Dieser Name ist bereits vergeben! Bitte wählen"
									+ " Sie einen anderen!", "Achtung!",
							JOptionPane.ERROR_MESSAGE);
					exportAsComponentDialog(eModel);
				}
			}
		}
	}

	/**
	 * Oeffnet den Dialog, der angibt, dass gerade die Checks durchgefuehrt
	 * werden. Der User wird gezwungen zu warten um weitere Aktionen
	 * auszufuehren, bis die Checks abgeschlossen sind, oder er bricht die
	 * Checks ab.
	 * 
	 * @param e
	 *            <code>EventObject</code> - Event, das diese Methode ausgeloest
	 *            hat
	 * @param eModel
	 *            <code>EditorModel</code> - Referenz auf das
	 *            <code>EditorModel</code>
	 */
	protected static void showCheckDialog(EventObject e, EditorModel eModel) {
		dialogPanel.removeAll();
		myFrame.setEnabled(false);

		waitDialog = new JDialog(myFrame, ModalityType.MODELESS);
		waitDialog.setIconImage(myFrame.getIconImage());
		waitDialog.setTitle("Durchführung der Checks");
		waitDialog.setPreferredSize(new Dimension(450, 240));
		waitDialog.setResizable(false);
		waitDialog.setLayout(new BorderLayout());
		waitDialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
		waitDialog.add(dialogPanel, BorderLayout.CENTER);
		waitDialog.add(Box.createHorizontalStrut(20), BorderLayout.WEST);
		waitDialog.add(Box.createVerticalStrut(20), BorderLayout.SOUTH);
		GridLayout gLayout = new GridLayout(4, 2);

		northPanel.setLayout(new BorderLayout());
		northPanel.add(Box.createVerticalStrut(20), BorderLayout.NORTH);
		JLabel startLabel = new JLabel("Starten der Checks...");
		startLabel.setFont(new Font(startLabel.getFont().getFontName(),
				Font.ITALIC, 14));
		northPanel.add(startLabel, BorderLayout.CENTER);
		northPanel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH);
		northPanel.add(Box.createHorizontalStrut(20), BorderLayout.WEST);
		waitDialog.add(northPanel, BorderLayout.NORTH);
		dialogPanel.setLayout(gLayout);
		dialogPanel.revalidate();
		waitDialog.validate();
		waitDialog.setVisible(true);
		waitDialog.pack();
		waitDialog.setLocation(
				myFrame.getX() + myFrame.getWidth() / 2 - waitDialog.getWidth()
						/ 2,
				myFrame.getY() + myFrame.getHeight() / 2
						- waitDialog.getHeight() / 2);

	}

	/**
	 * Gibt im JPanel fuer die Checks aus, ob der Test, ob alle Eingaenge belegt
	 * sind, erfolgreich war oder nicht
	 * 
	 * @param result
	 *            <code>boolean</code> - Ergebnis des Tests
	 */
	protected static void inputsCheck(boolean result) {
		dialogPanel.add(new JLabel("Alle Eingänge belegt:"));
		if (result) {
			dialogPanel.add(new JLabel(new ImageIcon(loader.getResource(UtilityConstants.ICON_PATH
					+ "test-okay.png"))));
			checkOk++;
		} else {
			dialogPanel.add(new JLabel(new ImageIcon(loader.getResource(UtilityConstants.ICON_PATH
					+ "test-fail.png"))));
		}
		dialogPanel.revalidate();
		waitDialog.validate();
		waitDialog.pack();
	}

	/**
	 * Gibt im JPanel fuer die Checks aus, ob der Test, ob die Schaltung leer
	 * ist, erfolgreich war oder nicht
	 * 
	 * @param result
	 *            <code>boolean</code> - Ergebnis des Tests
	 */
	protected static void circuitIsNotEmpty(boolean result) {
		checkOk = 0;
		dialogPanel.add(new JLabel("Schaltung nicht leer:"));
		if (result) {
			dialogPanel.add(new JLabel(new ImageIcon(loader.getResource(UtilityConstants.ICON_PATH
					+ "test-okay.png"))));
			checkOk++;
		} else {
			dialogPanel.add(new JLabel(new ImageIcon(loader.getResource(UtilityConstants.ICON_PATH
					+ "test-fail.png"))));
		}
		dialogPanel.revalidate();
		waitDialog.validate();
		waitDialog.pack();
	}

	/**
	 * Gibt im JPanel fuer die Checks aus, ob der Test, ob alle Subnetze auch
	 * mindestens einen Schalter und eine Lampe haben, erfolgreich war oder
	 * nicht
	 * 
	 * @param result
	 *            <code>boolean</code> - Ergebnis des Tests
	 */
	protected static void subnetCheck(boolean result) {
		dialogPanel.add(new JLabel("Keine fehlerhaften Teilnetze:"));
		if (result) {
			dialogPanel.add(new JLabel(new ImageIcon(loader.getResource(UtilityConstants.ICON_PATH
					+ "test-okay.png"))));
			checkOk++;
		} else {
			dialogPanel.add(new JLabel(new ImageIcon(loader.getResource(UtilityConstants.ICON_PATH
					+ "test-fail.png"))));
		}
		JLabel label = new JLabel(checkOk + " von " + checkCount
				+ " Tests erfolgreich");
		label.setFont(new Font(label.getFont().getFontName(), Font.ITALIC, 13));
		if (checkOk < checkCount) {
			label.setForeground(UtilityConstants.CHECK_FAILED);
		} else {
			label.setForeground(UtilityConstants.CHECK_OKAY);
		}
		dialogPanel.revalidate();
		waitDialog.validate();
		dialogPanel.add(label);
		waitDialog.pack();
	}

	/**
	 * In dieser Methode werden die Eigenschaften des uebergebenen
	 * <code>JFileChooser</code>-Objekts festgelegt.
	 * 
	 * @param fileChooser
	 *            <code>JFileChooser</code> - Das <code>JFileChooser</code>
	 *            -Objekt, dessen Eigenschaften festgelegt werden
	 * 
	 * @param extension
	 *            <code>String</code> - Erlaubte Dateiendung
	 */
	private static void calibrationOfFileChooser(JFileChooser fileChooser,
			String extension) {

		// Fuer die innere Klasse FileFilter wird diese Variable benoetigt
		final String commitedExtension = extension;

		// Bewirkt, dass der User nicht alle Dateien eines Ordners angezeigt
		// bekommt,...
		fileChooser.setAcceptAllFileFilterUsed(false);

		// ...sondern nur Dateien mit der gegebenen Endung
		fileChooser.setFileFilter(new FileFilter() {

			@Override
			public boolean accept(File f) {
				return f.isDirectory()
						|| f.getName().matches(".*\\" + commitedExtension);
			}

			@Override
			public String getDescription() {
				return "*" + commitedExtension + "-Dateien";
			}
		});
	}

	/**
	 * Hilfsmethode zum Anzeigen eines <code>JFileChooser</code> zum Laden einer
	 * Datei.
	 * 
	 * @param eModel
	 *            <code>EditorModel</code> - Referenz auf das
	 *            <code>EditorModel</code>
	 * 
	 * @param extension
	 *            <code>String</code> - Format der zu ladenden Datei
	 * 
	 * @param caller
	 *            <code>Object</code> - Ist entweder Referenz auf den
	 *            <code>ComponentImportListener</code> oder den
	 *            <code>LoadCircuitListener</code>
	 */
	private static void createLoadDialog(EditorModel eModel, String extension,
			Object caller) {
		JFileChooser fileChooser = new JFileChooser();

		// Setzt das Defaultverzeichnis, je nachdem von welcher Instanz caller
		// ist
		if (caller instanceof ComponentImportListener) {
			File sdDir = new File(UtilityConstants.SD_DIRECTORY);
			if (!sdDir.exists()) {
				sdDir.mkdir();
			}
			fileChooser.setCurrentDirectory(sdDir);
		} else if (caller instanceof LoadCircuitListener) {
			File circuitDir = new File(UtilityConstants.SAVED_CIRCUITS);
			if (!circuitDir.exists()) {
				circuitDir.mkdir();
			}
			fileChooser.setCurrentDirectory(circuitDir);
		}

		calibrationOfFileChooser(fileChooser, extension);
		int userSelection = fileChooser.showOpenDialog(myFrame);

		// User klickt im JFileChooser auf "Oeffnen"
		if (userSelection == JFileChooser.APPROVE_OPTION) {

			// Name der zu ladenden Datei
			String fileName = fileChooser.getSelectedFile().getName();

			// Falls der User die Dateiendung nicht angibt, wird diese
			// automatisch vervollstaendigt
			if (!fileName.toLowerCase().endsWith(extension)) {
				fileName = fileName + extension;
			}

			// Wird benoetigt zur Ueberpruefung, ob die Datei schon
			// existiert. Falls der User die Dateiendung nicht mit eingegeben
			// hatte, wurde diese zuvor vervollstaendigt. Dazu wird deshalb hier
			// ein neues "File"-Objekt erzeugt, das den aktualisierten Namen
			// enthaelt.
			File newFile = new File(fileChooser.getSelectedFile().getParent(),
					fileName);

			// Pfad der Datei, die geladen werden soll
			String path = newFile.toString();

			// Falls die Datei existiert, wird sie geladen. Andernfalls
			// erscheint ein Dialog, der dem User mitteilt, dass die gesuchte
			// Datei nicht existiert. Anschließend kann er erneut eine zu
			// ladende Datei auswaehlen
			if (newFile.exists()) {

				if (caller instanceof ComponentImportListener) {
					eModel.importComponent(path.split(".xml")[0]);
				} else if (caller instanceof LoadCircuitListener) {
					eModel.loadCircuit(path);
				}
			} else {
				JOptionPane.showMessageDialog(myFrame, newFile.getName()
						+ " existiert nicht!", "Achtung!",
						JOptionPane.ERROR_MESSAGE);
				loadDialog(eModel, extension, caller);
			}
		}
	}

	/**
	 * Setzt das Attribut myFrame.
	 * 
	 * @param locsiFrame
	 *            <code>LocsiFrame</code>
	 */
	public static void setMyFrame(LocsiFrame locsiFrame) {
		myFrame = locsiFrame;
	}

	/**
	 * Gibt das Attribut myFrame zurueck
	 * 
	 * @return <code>JFrame</code>
	 */
	public static JFrame getFrame() {
		return myFrame;
	}
}